# # 绘制匹配结果
# matched_image = cv2.drawMatches(target_image, keypoints_target, screenshot_gray, keypoints_screenshot, matches[:10],
#                                 None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
# # 在屏幕截图上绘制目标图像的中心点
# # cv2.circle(matched_image, (target_center_x, target_center_y), 5, (0, 255, 0), -1)
#
# # 显示匹配结果图像
# cv2.imshow('Matches', matched_image)
# cv2.waitKey(1)
# time.sleep(100)
import os
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,QMessageBox, QComboBox,QFormLayout
from PyQt5.QtCore import QTimer, QTime, Qt
import concurrent.futures
import pyautogui
import time
from pynput.mouse import Button
from pynput import mouse
from pynput import keyboard
from pynput import keyboard as k
import pydirectinput as pymouse
from pynput.keyboard import Key
import threading
import math
import inspect
import ctypes
import cv2
import numpy as np
import pygetwindow as gw

mouse = mouse.Controller()
keyboard = k.Controller()


def _async_raise(tid, exctype):
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")


def stop_thread(thread):
    _async_raise(thread.ident, SystemExit)

def qinka():
    global index
    global xx,number
    global t1
    xx_x=0
    xx_y = 0.6708333333
    num_x=0
    num_y = 0.4958333333
    print(xx,number)
    if xx == 1 or xx == '1':
        xx_x = 0.29765625
    elif xx == 2 or xx == '2':
        xx_x = 0.38203125
    elif xx == 3 or xx == '3':
        xx_x = 0.465625
    elif xx == 4 or xx == '4':
        xx_x = 0.55
    elif xx == 5 or xx == '5':
        xx_x = 0.634375

    if number == 1 or number =='1':
        num_x = 0.31640625
    elif number == 2 or number =='2':
        num_x = 0.42109375
    elif number == 3 or number =='3':
        num_x = 0.52734375
    elif number == 4 or number =='4':
        num_x = 0.63359375
    elif number == 5 or number =='5':
        num_x = 0.73984375
    print(xx_x, num_x)
    while (True):
        keyboard.press('e')
        time.sleep(0.1)
        keyboard.release('e')
        time.sleep(0.4)
        screenshot1 = pyautogui.screenshot(region=(app_window_x + 833, app_window_y + 30 + 533, 167, 31))
        zhbs = jianglicompare('./image/zhbs.png',screenshot1,'召唤boss')
        if not zhbs:
            continue
        try:
            stop_thread(t1)
        except:
            pass
        mouse.position = (
        app_window_x + app_window_width * xx_x, app_window_y + app_window_height - (app_window_height - 30) * xx_y)
        time.sleep(0.1)
        mouse.click(Button.left)
        time.sleep(0.1)
        mouse.position = (
            app_window_x + app_window_width * num_x, app_window_y + app_window_height - (app_window_height - 30) * num_y)
        time.sleep(0.1)
        mouse.click(Button.left)
        time.sleep(0.1)
        mouse.position = (
            app_window_x + app_window_width * 0.7171875,
            app_window_y + app_window_height - (app_window_height - 30) * 0.2361111111)
        time.sleep(0.1)
        mouse.click(Button.left)
        time.sleep(0.1)
        keyboard.press('r')
        time.sleep(0.1)
        keyboard.release('r')
        t1 = threading.Thread(target=shoot)  # 开枪
        try:
            t1.start()
        except:
            pass
        # while(True):

def dianji():
    while True:
        js, js_x, js_y = compareCv('./image/js.png', '点击确认')
        if js:
            mouse.position = (js_x,js_y)
            time.sleep(0.1)
            mouse.click(Button.left)

def shoot():
    time.sleep(5)
    pymouse.mouseDown()

def cfqk():
    global kaiqi
    global t2,t3,t6
    global brisk
    global app_window
    global app_window_x, app_window_y, app_window_width, app_window_height
    if kaiqi == 1:
        print("开启失败，你当前已经打开程序了")
    else:
        # 创建BRISK特征提取器
        brisk = cv2.BRISK_create()
        # 获取目标程序窗口
        app_window = gw.getWindowsWithTitle('穿越火线')[0]
        print(app_window.title)
        if(app_window.title != '穿越火线'):
            tanchuan('请先打开穿越火线再重新运行程序')
        else:
            # 获取程序窗口的位置和大小
            app_window_x, app_window_y, app_window_width, app_window_height = app_window.left, app_window.top, app_window.width, app_window.height
            kaiqi = 1
            t2 = threading.Thread(target=qinka)  # 清卡
            try:
                t2.start()
            except:
                pass
            t3 = threading.Thread(target=dianji)  # 清卡
            try:
                t3.start()
            except:
                pass
            print("开启其成功")

    # creatRoom()

def stop():
    global kaiqi
    if(kaiqi == 0):
        print("暂停失败，你还没开启程序")
        pass
    else:
        kaiqi = 0
        print("暂停中...")
        try:
            stop_thread(t2)
        except:
            pass
        time.sleep(0.5)
        try:
            pymouse.mouseUp()
            stop_thread(t1)
        except:
            pass
        try:
            stop_thread(t3)
        except:
            pass
        print("暂停完成")


brisk = None
# 获取目标程序窗口
app_window = None
# 获取程序窗口的位置和大小
app_window_x, app_window_y, app_window_width, app_window_height = (None,None,None,None)

index = 0 #总次数
kaiqi = 0

xx = 1
number = 1



def tanchuan(text):
    msg_box = QMessageBox()
    msg_box.setWindowTitle("提示")
    msg_box.setText(text)
    msg_box.setIcon(QMessageBox.Information)
    msg_box.exec_()


def printSum():
    app = QApplication(sys.argv)
    window = QWidget()
    window.setWindowTitle("cf清卡")
    window.setGeometry(100, 100, 300, 200)


    layout = QVBoxLayout()



    label = QLabel()
    label.setAlignment(Qt.AlignCenter)
    layout.addWidget(label)
    text = f"按7启动程序，按8停止程序\n\n\n"
    label.setText(text)

    label_1 = QLabel("选择清多少星的卡:", window)
    combo_box_1 = QComboBox(window)
    combo_box_1.addItem("1")
    combo_box_1.addItem("2")
    combo_box_1.addItem("3")
    combo_box_1.addItem("4")
    combo_box_1.addItem("5")

    label_2 = QLabel("选择第几个:", window)
    combo_box_2 = QComboBox(window)
    combo_box_2.addItem("1")
    combo_box_2.addItem("2")
    combo_box_2.addItem("3")
    combo_box_2.addItem("4")
    combo_box_2.addItem("5")

    layout.addWidget(label_1)
    layout.addWidget(combo_box_1)
    layout.addWidget(label_2)
    layout.addWidget(combo_box_2)
    button_layout = QHBoxLayout()
    start_button = QPushButton("开始")
    stop_button = QPushButton("停止")
    button_layout.addWidget(start_button)
    button_layout.addWidget(stop_button)
    layout.addLayout(button_layout)

    window.setLayout(layout)
    start_button.clicked.connect(cfqk)
    stop_button.clicked.connect(stop)
    combo_box_1.currentIndexChanged.connect(
        lambda index, index_param=1: handleComboBoxChange(index, index_param, label))
    combo_box_2.currentIndexChanged.connect(
        lambda index, index_param=2: handleComboBoxChange(index, index_param, label))
    desktop_rect = QApplication.desktop().availableGeometry()
    window.move(desktop_rect.topRight() - window.rect().topRight())
    window.show()

    timer = QTimer()
    timer.start()
    timer.setInterval(1000)
    timer.timeout.connect(lambda: update_text(label))
    sys.exit(app.exec_())

def handleComboBoxChange(index, index_param, label):
    global xx,number
    selected_value = label.sender().currentText()  # 或 label.sender().currentData()，根据实际情况选择适合的方法
    if index_param == 1:
        xx = selected_value
    elif index_param == 2:
        number = selected_value
    # 获取选择的值
    print(f"当前选择的是{xx}星卡，选择第{number}位置")

def update_text(label):
    text = f"按7启动程序，按8停止程序\n\n\n"
    label.setText(text)

def jianglicompare(target_image_path,screenshot,text):
    # 加载目标图像并检测关键点和计算特征描述符
    try:
        screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
        # 加载目标图片
        target_image = cv2.imread(target_image_path, cv2.COLOR_RGB2BGR)

        # 使用SIFT特征算法提取特征点和特征描述符
        sift = cv2.SIFT_create()
        kp1, des1 = sift.detectAndCompute(target_image, None)
        kp2, des2 = sift.detectAndCompute(screenshot, None)

        # 创建FLANN匹配器
        index_params = dict(algorithm=0, trees=5)
        search_params = dict(checks=50)
        flann = cv2.FlannBasedMatcher(index_params, search_params)

        # 使用FLANN匹配器进行特征点匹配
        matches = flann.knnMatch(des1, des2, k=2)

        # 进行比值测试，筛选出较好的匹配点
        good_matches = []
        for m, n in matches:
            if m.distance < 0.7 * n.distance:
                good_matches.append(m)

        # result_image = cv2.drawMatches(target_image, kp1, screenshot, kp2, good_matches, None,
        #                                flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
        # cv2.imshow("Matching Result", result_image)
        # cv2.waitKey(0)
        # cv2.destroyAllWindows()
        # 如果有足够的匹配点，进行点击操作
        if len(good_matches) >= 6:
            print(f'success：{text}，有{len(good_matches)}个相似点，定位成功')
            return True
        else:
            print(f'error：{text}，有{len(good_matches)}个相似点，没有定位成功')
            return False
    except:
        print(text, '没有定位成功')
        return False

def compareCv(target_image_path,text):
    # 加载目标图像并检测关键点和计算特征描述符
    target_image = cv2.imread(target_image_path, cv2.IMREAD_GRAYSCALE)
    keypoints_target, descriptors_target = brisk.detectAndCompute(target_image, None)
    # 获取屏幕截图
    screenshot = pyautogui.screenshot(region=(app_window_x, app_window_y, app_window_width, app_window_height))
    screenshot_gray = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2GRAY)

    # 在屏幕截图中检测关键点和计算特征描述符
    keypoints_screenshot, descriptors_screenshot = brisk.detectAndCompute(screenshot_gray, None)
    # 创建特征匹配器
    matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
    # 特征匹配
    matches = matcher.match(descriptors_target, descriptors_screenshot)
    # 根据距离排序匹配结果
    matches = sorted(matches, key=lambda x: x.distance)
    max_distance = matches[-1].distance
    normalized_distances = [match.distance / max_distance for match in matches]
    # 设置准确度阈值
    normalized_distance_threshold = 0.30
    # 获取最佳匹配的关键点
    best_match_index = np.argmin(normalized_distances)
    best_match = matches[best_match_index]
    # 获取最佳匹配的准确度评分和关键点
    best_normalized_distance = normalized_distances[best_match_index]
    best_keypoint = keypoints_screenshot[best_match.trainIdx]
    print(text,best_normalized_distance)


    # 将目标图像中心坐标转换为全局坐标
    if best_normalized_distance < normalized_distance_threshold:
        # 获取目标图像的中心坐标
        target_center_x = int(best_keypoint.pt[0])
        target_center_y = int(best_keypoint.pt[1])
        # 将目标图像中心坐标转换为全局坐标
        target_center_x_global = app_window_x + target_center_x
        target_center_y_global = app_window_y + target_center_y
        return True,target_center_x_global,target_center_y_global
    else:
        return False,0,0

def compareCv1(target_image_path,text):
    screenshot = pyautogui.screenshot(region=(app_window_x, app_window_y, app_window_width, app_window_height))
    screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)

    # 加载目标图片
    target_image = cv2.imread(target_image_path, 0)

    # 使用SIFT特征算法提取特征点和特征描述符
    sift = cv2.SIFT_create()
    kp1, des1 = sift.detectAndCompute(target_image, None)
    kp2, des2 = sift.detectAndCompute(screenshot, None)

    # 创建FLANN匹配器
    index_params = dict(algorithm=0, trees=5)
    search_params = dict(checks=50)
    flann = cv2.FlannBasedMatcher(index_params, search_params)

    # 使用FLANN匹配器进行特征点匹配
    matches = flann.knnMatch(des1, des2, k=2)

    # 进行比值测试，筛选出较好的匹配点
    good_matches = []
    for m, n in matches:
        if m.distance < 0.7 * n.distance:
            good_matches.append(m)

    # 如果有足够的匹配点，进行点击操作
    if len(good_matches) >= 10:
        # 获取目标图像的宽度和高度
        target_width = target_image.shape[1]
        target_height = target_image.shape[0]

        # 计算匹配点的平均位置
        sum_x = sum_y = 0
        for match in good_matches:
            sum_x += kp2[match.trainIdx].pt[0]
            sum_y += kp2[match.trainIdx].pt[1]
        avg_x = int(sum_x / len(good_matches))
        avg_y = int(sum_y / len(good_matches))

        # 计算在屏幕上的点击坐标
        click_x = app_window_x + avg_x
        click_y = app_window_y + avg_y
        print(click_x, click_y)
        print(text, '定位成功')
        return True, click_x, click_y
    else:
        print(text,'没有定位成功')
        return False, 0, 0

def timeOut():
    time.sleep(2100)
    stop()
    time.sleep(0.5)
    keyboard.press(Key.esc)
    time.sleep(0.1)
    keyboard.release(Key.esc)

    keyboard.press(Key.enter)
    time.sleep(0.1)
    keyboard.release(Key.enter)

    keyboard.press(Key.enter)
    time.sleep(0.1)
    keyboard.release(Key.enter)
    time.sleep(1)
    mouse.position = (app_window_x + app_window_width * 0.81875
                      , app_window_y + app_window_height - (app_window_height - 30) * 0.070833)
    mouse.click(Button.left)
    time.sleep(1)

    mouse.position = (app_window_x + app_window_width * 0.7734375
                      , app_window_y + app_window_height - (app_window_height - 30) * 0.1)
    mouse.click(Button.left)
    time.sleep(1)

    keyboard.press(Key.enter)
    time.sleep(0.1)
    keyboard.release(Key.enter)
    time.sleep(0.5)
    keyboard.press(Key.enter)
    time.sleep(0.1)
    keyboard.release(Key.enter)
    time.sleep(1)
    keyboard.press(Key.esc)
    time.sleep(0.1)
    keyboard.release(Key.esc)

t8 = threading.Thread(target=printSum)  # 打印信息
t2 = threading.Thread(target=qinka)  # 清卡
t1 = threading.Thread(target=shoot)  # 开枪
t3 = threading.Thread(target=dianji)  # 点击

t8.start()


with k.GlobalHotKeys({"7":cfqk,"8":stop}) as listener:
    listener.join()



